package com.coolgor.xcode;

import java.io.*;
import java.util.List;

public class StackDao {

    public static void run(String basePath, List<String[]> context) throws IOException {
        String outputPath = basePath + XcoderConfig.OutputPath + "/dao";
        String tableName = null;
        String className = null;
        String keyColumn = null;
        String keyParam = null;
        for (int i = 0; i < context.size(); i++) {
            switch (context.get(i)[0].toLowerCase()){
                case "table":
                    tableName = context.get(i)[1];
                    className = StringUtil.firstUpper(context.get(i)[2]);
                    break;
                case "key":
                    keyColumn = context.get(i)[1];
                    keyParam = context.get(i)[2];
                    break;
            }
        }
        // queryByID
        StringBuffer queryByID = new StringBuffer();
        queryByID.append("\t@Select(\"\"\"\n");
        queryByID.append("\t\t<script>\n");
        queryByID.append("\t\t\tSELECT\n");
        queryByID.append("\t\t\t\t*\n");
        queryByID.append("\t\t\tFROM\n");
        queryByID.append("\t\t\t\t"+tableName+"\n");
        queryByID.append("\t\t\tWHERE\n");
        queryByID.append("\t\t\t\t"+keyColumn+" = #{"+keyParam+"}\n");
        queryByID.append("\t\t</script>\n");
        queryByID.append("\t\"\"\")\n");

        // resultMap
        StringBuffer resultMap = new StringBuffer();
        resultMap.append("\t@Results(id = \""+StringUtil.firstUpper(className)+"Map\", value = {\n");

        // queryList
        StringBuffer queryList = new StringBuffer();
        queryList.append("\t@Select(\"\"\"\n");
        queryList.append("\t\t<script>\n");
        queryList.append("\t\t\tSELECT\n");
        queryList.append("\t\t\t\t*\n");
        queryList.append("\t\t\tFROM\n");
        queryList.append("\t\t\t\t"+tableName+"\n");
        queryList.append("\t\t\t<where>\n");

        // queryCount
        StringBuffer queryCount = new StringBuffer();
        queryCount.append("\t@Select(\"\"\"\n");
        queryCount.append("\t\t<script>\n");
        queryCount.append("\t\t\tSELECT\n");
        queryCount.append("\t\t\t\tcount(1)\n");
        queryCount.append("\t\t\tFROM\n");
        queryCount.append("\t\t\t\t"+tableName+"\n");
        queryCount.append("\t\t\t<where>\n");

        // ifStr
        StringBuffer ifStr = new StringBuffer();

        // insert
        StringBuffer insert = new StringBuffer();
        insert.append("\t@Insert(\"\"\"\n");
        insert.append("\t\t<script>\n");
        insert.append("\t\t\tINSERT INTO "+tableName+" (\n");

        // insertValue
        StringBuffer insertValue = new StringBuffer();
        insertValue.append("\t\t\t) VALUES (\n");

        // update
        StringBuffer update = new StringBuffer();
        update.append("\t@Update(\"\"\"\n");
        update.append("\t\t<script>\n");
        update.append("\t\t\tUPDATE "+tableName+"\n");
        update.append("\t\t\t<set>\n");



        for (int i = 0; i < context.size(); i++) {
            switch (context.get(i)[0].toLowerCase()){
                case "key":
                    resultMap.append("\t\t@Result(property = \""+context.get(i)[2]+"\", column = \""+context.get(i)[1]+"\"),\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand "+context.get(i)[1]+" = #{"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+"}\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    break;
                case "long","int","integer":
                    resultMap.append("\t\t@Result(property = \""+context.get(i)[2]+"\", column = \""+context.get(i)[1]+"\"),\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand "+context.get(i)[1]+" = #{"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+"}\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    insert.append("\t\t\t\t"+context.get(i)[1]+",\n");
                    insertValue.append("\t\t\t\t#{"+context.get(i)[2]+"},\n");
                    update.append("\t\t\t\t<if test=\""+context.get(i)[2]+" != null\">"+context.get(i)[1]+"=#{"+context.get(i)[2]+"},</if>\n");
                    break;
                case "string":
                    resultMap.append("\t\t@Result(property = \""+context.get(i)[2]+"\", column = \""+context.get(i)[1]+"\"),\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand "+context.get(i)[1]+" like '${"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+"}'\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    insert.append("\t\t\t\t"+context.get(i)[1]+",\n");
                    insertValue.append("\t\t\t\t#{"+context.get(i)[2]+"},\n");
                    update.append("\t\t\t\t<if test=\""+context.get(i)[2]+" != null\">"+context.get(i)[1]+"=#{"+context.get(i)[2]+"},</if>\n");
                    break;
                case "date","datetime":
                    resultMap.append("\t\t@Result(property = \""+context.get(i)[2]+"\", column = \""+context.get(i)[1]+"\"),\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand "+context.get(i)[1]+" = #{"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+"}\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand <![CDATA[ "+context.get(i)[1]+" >= #{"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+",jdbcType=DATE} ]]>\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    ifStr.append("\t\t\t\t<if test=\""+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+" != null\">\n");
                    ifStr.append("\t\t\t\t\tand <![CDATA[ "+context.get(i)[1]+" <= #{"+StringUtil.firstLower(className)+"Condition."+context.get(i)[2]+",jdbcType=DATE} ]]>\n");
                    ifStr.append("\t\t\t\t</if>\n");
                    insert.append("\t\t\t\t"+context.get(i)[1]+",\n");
                    insertValue.append("\t\t\t\t#{"+context.get(i)[2]+"},\n");
                    update.append("\t\t\t\t<if test=\""+context.get(i)[2]+" != null\">"+context.get(i)[1]+"=#{"+context.get(i)[2]+"},</if>\n");
                    break;
            }
        }
        // ###############
        if (resultMap.charAt(resultMap.length()-2) == ',') {
            resultMap.deleteCharAt(resultMap.length()-2);
        }
        resultMap.append("\t})\n");
        // ###############
        queryByID.append(resultMap);
        queryByID.append("\t"+className+" queryByID(@Param(\""+keyParam+"\") Long "+keyParam+");\n");
        // queryList ###############
        queryList.append(ifStr);
        queryList.append("\t\t\t</where>\n");
        queryList.append("\t\t\tLIMIT #{rowIndex},#{pageSize};\n");
        queryList.append("\t\t</script>\n");
        queryList.append("\t\"\"\")\n");
        queryList.append("\t@ResultMap(\""+className+"Map\")\n");
        queryList.append("\tList<"+className+"> queryList(@Param(\""+StringUtil.firstLower(className)+"Condition\") "+className+" "+StringUtil.firstLower(className)+"Condition,\n");
        queryList.append("\t\t\t\t\t\t\t@Param(\"rowIndex\") int rowIndex,\n");
        queryList.append("\t\t\t\t\t\t\t@Param(\"pageSize\") int pageSize);\n");
        // queryCount ###############
        queryCount.append(ifStr);
        queryCount.append("\t\t\t</where>\n");
        queryCount.append("\t\t</script>\n");
        queryCount.append("\t\"\"\")\n");
        queryCount.append("\tint queryCount(@Param(\""+StringUtil.firstLower(className)+"Condition\") "+className+" "+StringUtil.firstLower(className)+"Condition);\n");
        // insert ###############
        if (insert.charAt(insert.length()-2) == ',') {
            insert.deleteCharAt(insert.length()-2);
        }
        if (insertValue.charAt(insertValue.length()-2) == ',') {
            insertValue.deleteCharAt(insertValue.length()-2);
        }
        insert.append(insertValue);
        insert.append("\t\t\t)\n");
        insert.append("\t\t</script>\n");
        insert.append("\t\"\"\")\n");
        insert.append("\t@Options(useGeneratedKeys = true, keyColumn = \""+keyColumn+"\", keyProperty = \""+keyParam+"\")\n");
        insert.append("\tint insert("+className+" "+StringUtil.firstLower(className)+");\n");
        // update ###############
        if (update.charAt(update.length()-7) == ',') {
            update.deleteCharAt(update.length()-7);
        }
        update.append("\t\t\t</set>\n");
        update.append("\t\t\tWHERE\n");
        update.append("\t\t\t\t"+keyColumn+" = #{"+keyParam+"}\n");
        update.append("\t\t</script>\n");
        update.append("\t\"\"\")\n");
        update.append("\tint update("+className+" "+StringUtil.firstLower(className)+");\n");
        // delete ###############
        StringBuffer delete = new StringBuffer();
        delete.append("\t@Delete(\"\"\"\n");
        delete.append("\t\t<script>\n");
        delete.append("\t\t\tDELETE FROM "+tableName+"\n");
        delete.append("\t\t\tWHERE\n");
        StringBuffer deleteBatch = new StringBuffer();
        deleteBatch.append(delete);
        delete.append("\t\t\t\t"+keyColumn+" = #{"+keyParam+"}\n");
        delete.append("\t\t</script>\n");
        delete.append("\t\"\"\")\n");
        delete.append("\tint delete(Long "+keyParam+");\n");
        deleteBatch.append("\t\t\t\t"+keyColumn+" IN\n");
        deleteBatch.append("\t\t\t\t<foreach collection=\"list\" item=\""+keyParam+"\" open=\"(\" separator=\",\" close=\")\">\n");
        deleteBatch.append("\t\t\t\t\t#{"+keyParam+"}\n");
        deleteBatch.append("\t\t\t\t</foreach>\n");
        deleteBatch.append("\t\t</script>\n");
        deleteBatch.append("\t\"\"\")\n");
        deleteBatch.append("\tint deleteBatch(List<Long> idList);\n");

        // File writing ###############
        File file =new File(outputPath);
        if (!file.exists()) file.mkdirs();
        file = new File(outputPath+"/"+className+"Dao.java");
        if (!file.exists()) file.createNewFile();
        FileOutputStream fos = new FileOutputStream(file);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
        bw.newLine();
        bw.write("import org.apache.ibatis.annotations.*;\n");
        bw.write("import java.util.List;\n");
        bw.newLine();
        bw.newLine();
        bw.write("@Mapper\n");
        bw.write("public interface "+className+"Dao {\n");
        bw.newLine();
        bw.write(queryByID.toString());
        bw.newLine();
        bw.write(queryList.toString());
        bw.newLine();
        bw.write(queryCount.toString());
        bw.newLine();
        bw.write(insert.toString());
        bw.newLine();
        bw.write(update.toString());
        bw.newLine();
        bw.write(delete.toString());
        bw.newLine();
        bw.write(deleteBatch.toString());
        bw.newLine();
        bw.write("}");
        bw.close();
    }
}
